//  Inside Microsoft Exchange 2007 Web Services 
//  Chapter 12
//
//  Copyright (c) 2007 David Sterling, Ben Spain, Mark Taylor, Huw Upshall, Michael Mainer.  
//  All rights reserved.
//

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using ProxyHelpers.EWS;

namespace WalkAttachmentHeirarchy
{
    class Program
    {
        static void Main(string[] args)
        {
            ExchangeServiceBinding binding = new ExchangeServiceBinding();
            binding.Url = @"https://yourServer/ews/Exchange.asmx";
            binding.Credentials = new NetworkCredential("username", "password", "domain");

            // TODO:  You must supply a valid Id to WalkAttachmentHierarchy 
            //
            //WalkAttachmentHierarchy(binding, id);
        }

        /// <summary>
        /// Takes a parent item and displays its attachment hierarchy (deep 
        /// traversal).  This is the main entry point for this functionality. (Listing 12-28)
        /// </summary>
        /// <param name="binding">Binding to use for EWS calls</param>
        /// <param name="parentId">Id of parent item to walk</param>
        /// 
        public static void WalkAttachmentHierarchy(
                    ExchangeServiceBinding binding,
                    ItemIdType parentId)
        {
            // First, grab the item with its attachments.  We will also get the 
            // subject for display purposes
            //
            GetItemType getItemRequest = new GetItemType();
            getItemRequest.ItemShape = new ItemResponseShapeType(
                DefaultShapeNamesType.IdOnly,
               new PathToUnindexedFieldType(UnindexedFieldURIType.itemAttachments),
               new PathToUnindexedFieldType(UnindexedFieldURIType.itemSubject));

            getItemRequest.ItemIds = new BaseItemIdType[] { parentId };
            GetItemResponseType getItemResponse = binding.GetItem(getItemRequest);
            ItemInfoResponseMessageType getItemResponseMessage =
                        getItemResponse.ResponseMessages.Items[0]
                                 as ItemInfoResponseMessageType;

            if (getItemResponseMessage.ResponseCode != ResponseCodeType.NoError)
            {
                throw new Exception("GetItem failed.  Response Code: " +
                             getItemResponseMessage.ResponseCode.ToString());
            }
            ItemType item = getItemResponseMessage.Items.Items[0];
             
            Console.WriteLine("ParentItem subject: {0}", item.Subject);

            // Now, walk the attachments
            //
            WalkAttachmentHierarchyByItemType(binding, item, 0 /* initial offset*/);
        }

        /// <summary>
        /// Given an ItemType instance, walk the attachments and display metadata 
        /// about them
        /// </summary>
        /// <param name="binding">Binding to use for EWS calls</param>
        /// <param name="item">The ItemType instance to walk</param>
        /// <param name="offset">Offset used for display purposes</param>
        /// 
        public static void WalkAttachmentHierarchyByItemType(
                     ExchangeServiceBinding binding,
                     ItemType item,
                     int offset)
        {
            // Build up a prefix tab to show our heirarchy
            //
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < offset; i++)
            {
                builder.Append("\t");
            }
            string prefixTabs = builder.ToString();

            // If there are no attachments, say so.  Nothing to walk.
            //
            if (item.Attachments == null)
            {
                Console.WriteLine("{0} -- <No Attachments>", prefixTabs);
            }
            else
            {
                // Cycle through each attachment on the passed item
                //
                foreach (AttachmentType attachment in item.Attachments)
                {
                    FileAttachmentType fileAttachment = attachment as
                               FileAttachmentType;
                    if (fileAttachment != null)
                    {
                        // If it is a file attachment, the branch stops here.  File 
                        // attachments do not have attachments of their own.
                        //
                        Console.WriteLine("{0} -- FileAttachment: {1}",
                                        prefixTabs, fileAttachment.Name);
                    }
                    else
                    {
                        // If it is an item attachment, we need to grab the actual 
                        // attachment using GetAttachment so that we get the embedded 
                        // item
                        //
                        ItemAttachmentType itemAttachment = attachment as
                                  ItemAttachmentType;
                        Console.WriteLine("{0} -- ItemAttachment: {1}",
                                  prefixTabs, itemAttachment.Name);

                        GetAttachmentType getAttachmentRequest =
                                  new GetAttachmentType();
                        getAttachmentRequest.AttachmentIds = new
                                  RequestAttachmentIdType[] { itemAttachment.AttachmentId };
                        GetAttachmentResponseType getAttachmentResponse =
                                  binding.GetAttachment(getAttachmentRequest);
                        AttachmentInfoResponseMessageType attachInfo =
                                  getAttachmentResponse.ResponseMessages.Items[0]
                                          as AttachmentInfoResponseMessageType;

                        if (attachInfo.ResponseCode != ResponseCodeType.NoError)
                        {
                            Console.WriteLine("{0} -- ERROR calling GetAttachment.  " +
                                    "Response Code: {1}",
                                    prefixTabs,
                                    attachInfo.ResponseCode.ToString());
                        }
                        else
                        {
                            // If we sucessfully retrieve the item attachment, we want 
                            // to recursively walk its attachments.  So increment our 
                            // "tab offset" and call ourselves again.
                            //
                            ItemType embeddedItem = (attachInfo.Attachments[0] as
                                       ItemAttachmentType).Item;
                            WalkAttachmentHierarchyByItemType(
                                       binding,
                                       embeddedItem,
                                       offset + 1);
                        }
                    }
                }
            }
        }
    }
}
